package com.gitee.wsl.func.procedure.sample

import com.gitee.wsl.ext.base.getOne
import com.gitee.wsl.ext.base.getTwo
import com.gitee.wsl.func.predicate.Predicate
import com.gitee.wsl.func.procedure.Procedure

/**
 * CaseProcedure allows developers to create an object form of a case statement, which instead of being based on
 * a single switch value is based on a list of predicate / procedure combinations. For the first predicate
 * that returns true for a given value in the case statement, the corresponding procedure will be executed.
 */
class CaseProcedure<T> : Procedure<T> {
    private val predicateProcedures = mutableListOf<Pair<Predicate<in T>, Procedure<in T>>>()
    private var defaultProcedure: Procedure<in T>? = null

    constructor(defaultProcedure: Procedure<in T>?) {
        this.defaultProcedure = defaultProcedure
    }

    constructor()

    fun addCase(predicate: Predicate<in T>, procedure: Procedure<in T>): CaseProcedure<T> {
        this.predicateProcedures.add(predicate to procedure)
        return this
    }

    fun setDefault(procedure: Procedure<in T>): CaseProcedure<T> {
        this.defaultProcedure = procedure
        return this
    }

    override fun value(each: T) {
        val localSize: Int = this.predicateProcedures.size
        for (i in 0..<localSize) {
            val pair = this.predicateProcedures[i]
            if (pair.getOne().accept(each)) {
                pair.getTwo().value(each)
                return
            }
        }
        if (this.defaultProcedure != null) {
            this.defaultProcedure!!.value(each)
        }
    }

    override fun toString(): String {
        return "new CaseProcedure(" + this.predicateProcedures + ')'
    }

}
